import org.apache.log4j.Logger;

import se480.io.StdIn;
import se480.paf.filters.ActiveFilter;
import se480.paf.filters.impl.CleanWordsFilter;
import se480.paf.filters.impl.CountWordFreqFilter;
import se480.paf.filters.impl.FileReaderFilter;
import se480.paf.filters.impl.FindFreqWordsSink;
import se480.paf.filters.impl.Lines2WordsFilter;
import se480.paf.filters.impl.StemWordsFilter;
import se480.paf.pipes.Item;
import se480.paf.pipes.Pipe;
import se480.paf.pipes.impl.PipeImpl;
import se480.paf.pipes.impl.Queue;

/**
 * This is the main controller class for the KWIC processing system.
 * This creates all the filters as active filters and connects them
 * with their in- and out-pipes.
 * 
 * Type a '-' in your console to end the program.
 * 
 * @author mmichalak
 *
 */
public class ControllerMain {
	static Logger logger = Logger.getLogger("ControllerMain");
	
	public static void main(String[] args) {
		
		ControllerMain controllerMain = new ControllerMain();

		controllerMain.startSystem();
        
        // Wait for keyboard inputs.  Type '-' to end program
        while (!StdIn.isEmpty()) {
            String item = StdIn.readString();
            if (item.equals("-")) break;
        }
        
        logger.info("Exiting program......");
	}
	
	
	/**
	 * This starts up the pipe and filter system.
	 * It starts all the filter threads and connects
	 * them to their respective pipes
	 */
	public void startSystem() {
		// Pipes
    	Pipe<Item> read2WordsPipe = new PipeImpl<Item>(); 
    	Pipe<Item> words2StopPipe = new PipeImpl<Item>();
    	Pipe<Item> cleanWords2StemPipe = new PipeImpl<Item>();
    	Pipe<Item> stem2WordCountPipe = new PipeImpl<Item>();
    	Pipe<Item> wordCount2OutputPipe = new PipeImpl<Item>();
        
        // Filter 1 - read files
    	ActiveFilter fileReaderFilter = new FileReaderFilter();
    	fileReaderFilter.setOutPipe(read2WordsPipe);
    	fileReaderFilter.setSleep(80);
        Thread thread1 = new Thread(fileReaderFilter);
        thread1.setDaemon(true);
        logger.info("Starting Filter..." + fileReaderFilter.getName());
        thread1.start();

        // Filter 2 - parse lines into words
    	ActiveFilter lines2WordsFilter = new Lines2WordsFilter();
    	lines2WordsFilter.setInPipe(read2WordsPipe);
    	lines2WordsFilter.setOutPipe(words2StopPipe);
    	lines2WordsFilter.setSleep(30);
        Thread thread2 = new Thread(lines2WordsFilter);
        thread2.setDaemon(true);
        logger.info("Starting Filter..." + lines2WordsFilter.getName());
        thread2.start();
        
		// Filter 3 - remove stop words and clean words
        ActiveFilter cleanWordsFilter = new CleanWordsFilter();
        cleanWordsFilter.setInPipe(words2StopPipe);
        cleanWordsFilter.setOutPipe(cleanWords2StemPipe);
        cleanWordsFilter.setSleep(35);
        Thread thread3 = new Thread(cleanWordsFilter);
        thread3.setDaemon(true);
        logger.info("Starting Filter..." + cleanWordsFilter.getName());
        thread3.start();
        
		// Filter 4 - Stem words
        ActiveFilter stemWordsFilter = new StemWordsFilter();
        stemWordsFilter.setInPipe(cleanWords2StemPipe);
        stemWordsFilter.setOutPipe(stem2WordCountPipe);
        stemWordsFilter.setSleep(40);
        Thread thread4 = new Thread(stemWordsFilter);
        thread4.setDaemon(true);
        logger.info("Starting Filter..." + stemWordsFilter.getName());
        thread4.start();
        
		// Filter 5 - Count word frequencies
        ActiveFilter countWordFreqFilter = new CountWordFreqFilter();
        countWordFreqFilter.setInPipe(stem2WordCountPipe);
        countWordFreqFilter.setOutPipe(wordCount2OutputPipe);
        countWordFreqFilter.setSleep(45);
        Thread thread5 = new Thread(countWordFreqFilter);
        thread5.setDaemon(true);
        logger.info("Starting Filter..." + countWordFreqFilter.getName());
        thread5.start();
        
		// Filter 6 - Find most freq words
        ActiveFilter findFreqWordsSink = new FindFreqWordsSink();
        findFreqWordsSink.setInPipe(wordCount2OutputPipe);
        // No output pipe
        findFreqWordsSink.setSleep(50);
        Thread thread6 = new Thread(findFreqWordsSink);
        thread6.setDaemon(true);
        logger.info("Starting Filter..." + findFreqWordsSink.getName());
        thread6.start();
        
	}
	
}
